package com.example.log.alarm.util;

import com.example.log.alarm.spy.BootstrapQueuedSpy;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;

/**
 * @program: spring-agent
 * @description:
 * @author: zt22328 赵儒定
 * @create: 2023-05-06 17:59
 **/
@Slf4j
public class BootstrapSpyUtil {

    private static final String BOOTSTRAP_QUEUED_SPY_CLASS_NAME = BootstrapQueuedSpy.class.getName() + "_internal";

    public static List<Map<String, Object>> getThrowable(int size) {
        try {
            Class<?> aClass = Class.forName(BOOTSTRAP_QUEUED_SPY_CLASS_NAME);
            Field throwableQueue = aClass.getDeclaredField("throwableQueue");
            throwableQueue.setAccessible(true);
            BlockingQueue<Map<String, Object>> queue = (BlockingQueue<Map<String, Object>>) throwableQueue.get(null);
            List<Map<String, Object>> list = new ArrayList<>(size*2);
            queue.drainTo(list, size);
            return list;
        } catch (Exception e) {
            return Collections.EMPTY_LIST;
        }
    }

    public static List<Map<String, Object>> getThreadPools(int size) {
        try {
            Class<?> aClass = Class.forName(BOOTSTRAP_QUEUED_SPY_CLASS_NAME);
            Field threadPoolQueue = aClass.getDeclaredField("threadPoolQueue");
            threadPoolQueue.setAccessible(true);
            BlockingQueue<Map<String, Object>> queue = (BlockingQueue<Map<String, Object>>) threadPoolQueue.get(null);
            List<Map<String, Object>> list = new ArrayList<>(size*2);
            queue.drainTo(list, size);
            return list;
        } catch (Exception e) {
            return Collections.EMPTY_LIST;
        }
    }

    public static List<Map<String, Object>> getThreadPoolRejects(int size) {
        try {
            Class<?> aClass = Class.forName(BOOTSTRAP_QUEUED_SPY_CLASS_NAME);
            Field threadPoolQueue = aClass.getDeclaredField("threadPoolRejectQueue");
            threadPoolQueue.setAccessible(true);
            BlockingQueue<Map<String, Object>> queue = (BlockingQueue<Map<String, Object>>) threadPoolQueue.get(null);
            List<Map<String, Object>> list = new ArrayList<>(size*2);
            queue.drainTo(list, size);
            return list;
        } catch (Exception e) {
            return Collections.EMPTY_LIST;
        }
    }

}
